import {Component, Input, OnInit} from '@angular/core';
import {UtilComponent} from '../../interface/util-component.interface';
import {DragRotateAndZoom} from 'ol/interaction';
import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import {LineString, Point, Polygon} from 'ol/geom.js';
import {defaults as defaultInteractions, Pointer as PointerInteraction} from 'ol/interaction.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import {TileJSON, Vector as VectorSource} from 'ol/source.js';
import {Fill, Icon, Stroke, Style} from 'ol/style.js';
import {transform} from 'ol/proj';
import XYZ from 'ol/source/XYZ';

@Component({
    selector: 'kylin-custom-interactions',
    templateUrl: './custom-interactions.component.html',
    styleUrls: ['./custom-interactions.component.less']
})
export class CustomInteractionsComponent implements OnInit, UtilComponent {

    hasContent = true;
    map: Map;

    @Input() set data(val) {
        Object.assign(this, val);
    }

    customerInteraction: any;
    vectorLayer: any;
    originTarget: any;
    originH: any;
    originW: any;
    newTarget: any;
    originDisplay: any;

    constructor() {
    }

    ngOnInit() {
        this.turnOn2();
    }

    turnOn() {
        const CustomerDrag = this.customerDrag();
        const pointFeature = new Feature(new Point([0, 0]));

        const lineFeature = new Feature(
            new LineString([[-1e7, 1e6], [-1e6, 3e6]].map(item => {
                return transform(item, 'EPSG:3857', 'EPSG:3857')
            })));

        const polygonFeature = new Feature(
            new Polygon([
                    [
                        [-3e6, -1e6], [-3e6, 1e6],
                        [-1e6, 1e6], [-1e6, -1e6], [-3e6, -1e6]
                    ]
                ].map(line => {
                    return line.map(item => {
                        return transform(item, 'EPSG:3857', 'EPSG:3857')
                    })
                })
            ));

        this.customerInteraction = new CustomerDrag();
        this.vectorLayer = new VectorLayer({
            source: new VectorSource({
                features: [pointFeature, lineFeature, polygonFeature],
            }),
            style: new Style({
                image: new Icon(/** @type {module:ol/style/Icon~Options} */ ({
                    anchor: [0.5, 46],
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'pixels',
                    opacity: 0.95,
                    src: './assets/img/castleMaker.png'
                } as any)),
                stroke: new Stroke({
                    width: 3,
                    color: [255, 0, 0, 1]
                }),
                fill: new Fill({
                    color: [0, 0, 255, 0.6]
                })
            })
        });
        this.map.addLayer(this.vectorLayer);
        this.map.addInteraction(this.customerInteraction);


    }

    turnOn2() {
        // 因首页底图导致要素无法拖动，暂时用其他底图做替换
        this.originTarget = this.map.getTargetElement();
        this.originH = this.originTarget.style.height;
        this.originW = this.originTarget.style.width;
        this.originDisplay = this.originTarget.style.display;
        this.originTarget.style.display = 'none';
        this.newTarget = document.createElement('div');
        this.newTarget.style.height = this.originH;
        this.newTarget.style.width = this.originW;
        this.originTarget.parentNode.insertBefore(this.newTarget, this.originTarget.nextElementSibling);

        const CustomerDrag = this.customerDrag();
        const pointFeature = new Feature(new Point([0, 0]));

        const lineFeature = new Feature(
            new LineString([[-1e7, 1e6], [-1e6, 3e6]]));

        const polygonFeature = new Feature(
            new Polygon([
                    [
                        [-3e6, -1e6], [-3e6, 1e6],
                        [-1e6, 1e6], [-1e6, -1e6], [-3e6, -1e6]
                    ]
                ]
            ));

        this.customerInteraction = new CustomerDrag();
        this.vectorLayer = new VectorLayer({
            source: new VectorSource({
                features: [pointFeature, lineFeature, polygonFeature]
            }),
            style: new Style({
                image: new Icon(/** @type {module:ol/style/Icon~Options} */ ({
                    anchor: [0.5, 46],
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'pixels',
                    opacity: 0.95,
                    src: './assets/img/castleMaker.png'
                } as any)),
                stroke: new Stroke({
                    width: 3,
                    color: [255, 0, 0, 1]
                }),
                fill: new Fill({
                    color: [0, 0, 255, 0.6]
                })
            })
        });
        this.map = new Map({
            interactions: defaultInteractions().extend([this.customerInteraction]),
            layers: [
                new TileLayer({
                    source: new XYZ({
                        url: 'http://webst0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
                    })
                }),
                this.vectorLayer
            ],
            target: this.newTarget,
            view: new View({
                center: [0, 0],
                zoom: 2
            })
        });
    }

    turnOff() {
        this.originTarget.style.height = this.originH;
        this.originTarget.style.width = this.originW;
        this.originTarget.style.display = this.originDisplay;

        this.newTarget.remove();

        this.map.removeInteraction(this.customerInteraction);
        this.map.removeLayer(this.vectorLayer);
    }

    cancel(options?: any): any {
        this.turnOff();
    }

    customerDrag() {
        /**
         * @constructor
         * @extends {module:ol/interaction/Pointer}
         */
        return (function (pointerInteraction) {
            function Drag() {
                pointerInteraction.call(this, {
                    handleDownEvent: handleDownEvent,
                    handleDragEvent: handleDragEvent,
                    handleMoveEvent: handleMoveEvent,
                    handleUpEvent: handleUpEvent
                });

                /**
                 * @type {module:ol/pixel~Pixel}
                 * @private
                 */
                this.coordinate_ = null;

                /**
                 * @type {string|undefined}
                 * @private
                 */
                this.cursor_ = 'pointer';

                /**
                 * @type {module:ol/Feature~Feature}
                 * @private
                 */
                this.feature_ = null;

                /**
                 * @type {string|undefined}
                 * @private
                 */
                this.previousCursor_ = undefined;
            }

            if (pointerInteraction) {
                Drag.__proto__ = pointerInteraction;
            }
            Drag.prototype = Object.create(pointerInteraction && pointerInteraction.prototype);
            Drag.prototype.constructor = Drag;

            return Drag;
        }(PointerInteraction));


        /**
         * @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt Map browser event.
         * @return {boolean} `true` to start the drag sequence.
         */
        function handleDownEvent(evt) {
            const map = evt.map;

            const feature = map.forEachFeatureAtPixel(evt.pixel,
                function (featureT) {
                    return featureT;
                });

            if (feature) {
                this.coordinate_ = evt.coordinate;
                this.feature_ = feature;
            }

            return !!feature;
        }


        /**
         * @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt Map browser event.
         */
        function handleDragEvent(evt) {
            const deltaX = evt.coordinate[0] - this.coordinate_[0];
            const deltaY = evt.coordinate[1] - this.coordinate_[1];

            const geometry = this.feature_.getGeometry();
            geometry.translate(deltaX, deltaY);

            this.coordinate_[0] = evt.coordinate[0];
            this.coordinate_[1] = evt.coordinate[1];
        }


        /**
         * @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt Event.
         */
        function handleMoveEvent(evt) {
            if (this.cursor_) {
                const map = evt.map;
                const feature = map.forEachFeatureAtPixel(evt.pixel,
                    function (featureT) {
                        return featureT;
                    });
                const element = evt.map.getTargetElement();
                if (feature) {
                    if (element.style.cursor !== this.cursor_) {
                        this.previousCursor_ = element.style.cursor;
                        element.style.cursor = this.cursor_;
                    }
                } else if (this.previousCursor_ !== undefined) {
                    element.style.cursor = this.previousCursor_;
                    this.previousCursor_ = undefined;
                }
            }
        }


        /**
         * @return {boolean} `false` to stop the drag sequence.
         */
        function handleUpEvent() {
            this.coordinate_ = null;
            this.feature_ = null;
            return false;
        }
    }
}
